/* frida hook android logcat hook
 * @link https://github.com/interference-security/frida-scripts/tree/master/android
 * @link https://gitee.com/horseluke/snippet/tree/master/2022-android-frida-script
 * @author @interference-security @horseluke
 */

var ___localStackid = 0;


function buildLogDataCell(msg, args){

	var result = {};

	result.id = ++___localStackid;
	result.date = new Date();
	result.time = result.date.getHours() + ":" + result.date.getMinutes() + ":" + result.date.getSeconds();
	result.args = args;
	result.msg = msg;

	result.stack = "";

    var Exception = Java.use("java.lang.Exception");
    var ins = Exception.$new("Exception");
    var straces = ins.getStackTrace();
	do{
		if (undefined == straces || null == straces) {
			break;
		}
		for (var i = 0; i < straces.length; i++) {
			var str = "   " + straces[i].toString();
			result.stack += str + "\r\n";
		}
	}while(false);

    Exception.$dispose();

	return result;
}


function displayLogDataCell(logDataCell){

	console.log("\r\n[# " + logDataCell.id + "]===========start===========");

	console.log("\r\n[# " + logDataCell.id + "][" + logDataCell.time + "]" + logDataCell.msg);
	for(var i = 0; i < logDataCell.args.length; i++){
		try{
			console.log("\r\n[# " + logDataCell.id + "]\targs " + (i + 1) + ": " + logDataCell.args[i].toString());
		}catch(e){
			console.log("\r\n[# " + logDataCell.id + "]\targs " + (i + 1) + ": " + logDataCell.args[i]);
		}
	}

	console.log("\r\n[# " + logDataCell.id + "]\tstack:\r\n" + logDataCell.stack);

	console.log("\r\n[# " + logDataCell.id + "]===========end===========");

}



Java.perform(function() {
	var class_name = Java.use("android.util.Log");
	//isLoggable
	class_name.isLoggable.overload("java.lang.String", "int").implementation = function (arg1, arg2) {

		displayLogDataCell(buildLogDataCell("isLoggable was called", [arg1, arg2]));

		//var temp = this.isLoggable(arg1, arg2);
		//return temp;
		return true;
	}

	//DEBUG
	class_name.d.overload("java.lang.String", "java.lang.String").implementation = function (arg1, arg2) {

		displayLogDataCell(buildLogDataCell("DEBUG (d)", [arg1, arg2]));

		var temp = this.d(arg1, arg2);
		return temp;

	}
	class_name.d.overload("java.lang.String", "java.lang.String", "java.lang.Throwable").implementation = function (arg1, arg2, arg3) {

		displayLogDataCell(buildLogDataCell("DEBUG (d)", [arg1, arg2, arg3]));

		var temp = this.d(arg1, arg2, arg3);
		return temp;

	}
	//ERROR
	class_name.e.overload("java.lang.String", "java.lang.String").implementation = function (arg1, arg2) {

		displayLogDataCell(buildLogDataCell("ERROR (e)", [arg1, arg2]));

		var temp = this.e(arg1, arg2);
		return temp;

	}
	class_name.e.overload("java.lang.String", "java.lang.String", "java.lang.Throwable").implementation = function (arg1, arg2, arg3) {

		displayLogDataCell(buildLogDataCell("ERROR (e)", [arg1, arg2, arg3]));

		var temp = this.e(arg1, arg2, arg3);
		return temp;

	}
	//INFO
	class_name.i.overload("java.lang.String", "java.lang.String").implementation = function (arg1, arg2) {
		
		displayLogDataCell(buildLogDataCell("INFO (i)", [arg1, arg2]));

		var temp = this.i(arg1, arg2);
		return temp;

	}
	class_name.i.overload("java.lang.String", "java.lang.String", "java.lang.Throwable").implementation = function (arg1, arg2, arg3) {

		displayLogDataCell(buildLogDataCell("INFO (i)", [arg1, arg2, arg3]));

		var temp = this.i(arg1, arg2, arg3);
		return temp;

	}
	//VERBOSE
	class_name.v.overload("java.lang.String", "java.lang.String").implementation = function (arg1, arg2) {

		displayLogDataCell(buildLogDataCell("VERBOSE (v)", [arg1, arg2]));

		var temp = this.v(arg1, arg2);
		return temp;

	}
	class_name.v.overload("java.lang.String", "java.lang.String", "java.lang.Throwable").implementation = function (arg1, arg2, arg3) {

		displayLogDataCell(buildLogDataCell("VERBOSE (v)", [arg1, arg2, arg3]));

		var temp = this.v(arg1, arg2, arg3);
		return temp;

	}
	//WARNING
	class_name.w.overload("java.lang.String", "java.lang.String").implementation = function (arg1, arg2) {

		displayLogDataCell(buildLogDataCell("WARNING (w)", [arg1, arg2]));

		var temp = this.w(arg1, arg2);
		return temp;

	}
	class_name.w.overload("java.lang.String", "java.lang.Throwable").implementation = function (arg1, arg2) {

		displayLogDataCell(buildLogDataCell("WARNING (w)", [arg1, arg2]));

		var temp = this.w(arg1, arg2);
		return temp;

	}
	class_name.w.overload("java.lang.String", "java.lang.String", "java.lang.Throwable").implementation = function (arg1, arg2, arg3) {
		
		displayLogDataCell(buildLogDataCell("WARNING (w)", [arg1, arg2, arg3]));

		var temp = this.w(arg1, arg2, arg3);
		return temp;


	}
	//What a Terrible Failure (WTF)
	class_name.wtf.overload("java.lang.String", "java.lang.String").implementation = function (arg1, arg2) {

		displayLogDataCell(buildLogDataCell("WTF (wtf)", [arg1, arg2]));

		var temp = this.wtf(arg1, arg2);
		return temp;


	}
	class_name.wtf.overload("java.lang.String", "java.lang.Throwable").implementation = function (arg1, arg2) {

		displayLogDataCell(buildLogDataCell("WTF (wtf)", [arg1, arg2]));

		var temp = this.wtf(arg1, arg2);
		return temp;

	}

	class_name.wtf.overload("java.lang.String", "java.lang.String", "java.lang.Throwable").implementation = function (arg1, arg2, arg3) {

		displayLogDataCell(buildLogDataCell("WTF (wtf)", [arg1, arg2, arg3]));

		var temp = this.wtf(arg1, arg2, arg3);
		return temp;


	}
});
